package cn.com.anypay.manager.common.utils;

import org.springframework.stereotype.Component;

import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 微信认证状态参数管理工具类
 * 用于生成和验证微信OAuth2.0认证过程中的state参数，防止CSRF攻击
 */
@Component
public class WeChatStateUtils {
    
    /**
     * 存储状态参数的内存缓存
     * key: state参数, value: 状态信息Map
     */
    private final ConcurrentHashMap<String, Map<String, Object>> stateCache = new ConcurrentHashMap<>();
    
    /**
     * 随机数生成器
     */
    private final SecureRandom secureRandom = new SecureRandom();
    
    /**
     * 定时清理过期状态参数的执行器
     */
    private final ScheduledExecutorService cleanupExecutor = Executors.newSingleThreadScheduledExecutor();
    
    /**
     * 状态参数默认有效期（分钟）
     */
    private static final int DEFAULT_EXPIRE_MINUTES = 10;
    
    public WeChatStateUtils() {
        // 启动定时清理任务，每5分钟执行一次
        cleanupExecutor.scheduleAtFixedRate(this::cleanupExpiredStates, 5, 5, TimeUnit.MINUTES);
    }
    
    /**
     * 生成状态参数
     * 
     * @return 生成的状态参数
     */
    public String generateState() {
        return generateState(DEFAULT_EXPIRE_MINUTES);
    }
    
    /**
     * 生成状态参数
     * 
     * @param expireMinutes 有效期（分钟）
     * @return 生成的状态参数
     */
    public String generateState(int expireMinutes) {
        // 生成32字节的随机数据
        byte[] randomBytes = new byte[32];
        secureRandom.nextBytes(randomBytes);
        
        // 使用Base64编码生成状态参数
        String state = Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
        
        // 存储状态参数和创建时间
        Map<String, Object> stateInfo = new HashMap<>();
        stateInfo.put("createTime", System.currentTimeMillis());
        stateInfo.put("expireMinutes", expireMinutes);
        stateCache.put(state, stateInfo);
        
        return state;
    }
    
    /**
     * 验证状态参数
     * 
     * @param state 要验证的状态参数
     * @return 验证是否成功
     */
    public boolean validateState(String state) {
        return validateState(state, DEFAULT_EXPIRE_MINUTES);
    }
    
    /**
     * 验证状态参数
     * 
     * @param state 要验证的状态参数
     * @param expireMinutes 有效期（分钟）
     * @return 验证是否成功
     */
    public boolean validateState(String state, int expireMinutes) {
        if (state == null || state.trim().isEmpty()) {
            return false;
        }
        
        Map<String, Object> stateInfo = stateCache.get(state);
        if (stateInfo == null) {
            return false;
        }
        
        // 检查是否过期
        Long createTime = (Long) stateInfo.get("createTime");
        if (createTime == null) {
            return false;
        }
        
        long currentTime = System.currentTimeMillis();
        long expireTime = createTime + (expireMinutes * 60 * 1000L);
        
        if (currentTime > expireTime) {
            // 移除过期的状态参数
            stateCache.remove(state);
            return false;
        }
        
        return true;
    }
    
    /**
     * 验证并消费状态参数（一次性使用）
     * 
     * @param state 要验证的状态参数
     * @return 验证是否成功
     */
    public boolean validateAndConsumeState(String state) {
        return validateAndConsumeState(state, DEFAULT_EXPIRE_MINUTES);
    }
    
    /**
     * 验证并消费状态参数（一次性使用）
     * 
     * @param state 要验证的状态参数
     * @param expireMinutes 有效期（分钟）
     * @return 验证是否成功
     */
    public boolean validateAndConsumeState(String state, int expireMinutes) {
        if (validateState(state, expireMinutes)) {
            // 验证成功后立即移除，确保一次性使用
            stateCache.remove(state);
            return true;
        }
        return false;
    }
    
    /**
     * 获取状态信息
     * 
     * @param state 状态参数
     * @return 状态信息Map，如果不存在则返回null
     */
    public Map<String, Object> getStateInfo(String state) {
        if (state == null || state.trim().isEmpty()) {
            return null;
        }
        
        Map<String, Object> stateInfo = stateCache.get(state);
        if (stateInfo == null) {
            return null;
        }
        
        // 检查是否过期
        Long createTime = (Long) stateInfo.get("createTime");
        if (createTime == null) {
            return null;
        }
        
        Integer expireMinutes = (Integer) stateInfo.get("expireMinutes");
        if (expireMinutes == null) {
            expireMinutes = DEFAULT_EXPIRE_MINUTES;
        }
        
        long currentTime = System.currentTimeMillis();
        long expireTime = createTime + (expireMinutes * 60 * 1000L);
        
        if (currentTime > expireTime) {
            // 移除过期的状态参数
            stateCache.remove(state);
            return null;
        }
        
        // 返回状态信息的副本
        return new HashMap<>(stateInfo);
    }
    
    /**
     * 更新状态信息
     * 
     * @param state 状态参数
     * @param key 信息键
     * @param value 信息值
     * @return 更新是否成功
     */
    public boolean updateStateInfo(String state, String key, Object value) {
        if (state == null || state.trim().isEmpty() || key == null) {
            return false;
        }
        
        Map<String, Object> stateInfo = stateCache.get(state);
        if (stateInfo == null) {
            return false;
        }
        
        // 检查是否过期
        if (!validateState(state)) {
            return false;
        }
        
        stateInfo.put(key, value);
        return true;
    }
    
    /**
     * 清理过期的状态参数
     */
    private void cleanupExpiredStates() {
        long currentTime = System.currentTimeMillis();
        stateCache.entrySet().removeIf(entry -> {
            Map<String, Object> stateInfo = entry.getValue();
            Long createTime = (Long) stateInfo.get("createTime");
            if (createTime == null) {
                return true; // 移除无效数据
            }
            
            Integer expireMinutes = (Integer) stateInfo.get("expireMinutes");
            if (expireMinutes == null) {
                expireMinutes = DEFAULT_EXPIRE_MINUTES;
            }
            
            long expireTime = createTime + (expireMinutes * 60 * 1000L);
            return currentTime > expireTime;
        });
    }
    
    /**
     * 获取当前缓存中的状态参数数量
     * 
     * @return 状态参数数量
     */
    public int getStateCount() {
        return stateCache.size();
    }
    
    /**
     * 清空所有状态参数
     */
    public void clearAllStates() {
        stateCache.clear();
    }
    
    /**
     * 销毁资源
     */
    public void destroy() {
        cleanupExecutor.shutdown();
        try {
            if (!cleanupExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                cleanupExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            cleanupExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
        stateCache.clear();
    }
}